/*
 * main.c
 *
 *  Created on: 2012/09/24
 *      Author: owner
 */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>

#include "typedef.h"
#include "Id.h"
#include "lib_func.h"
#include "core.h"
#include "trace.h"
#include "core_internal.h"
#include "core_table.h"
#include "trace_cmd_table.h"
#include "./cg/cg.h"
#include "coredef.h"

//#include "../CCore/trace/trace_cmd/trace_cmd.h"
//static CHAR file[OS_FULLPATH];

#include "db.h"
#include "rule_if.h"
#include "rule_inout.h"
#include "TraceAst.h"

static CHAR buf_conf[OS_FULLPATH];
static CHAR buf_ws[OS_FULLPATH];

static time_t g_time_start;

void thread_time(void)
{
	time_t cur;
	while(1)
	{
		sleep(60);
		cur = time(NULL);
		if(cur-g_time_start >= 3600)
		{
			printf("\nTime over! (%d s)\n",cur-g_time_start);

			if (stInputInfo.inOutMsgEng != NULL ) {
				writeXML_ENG(stInputInfo.inOutMsgEng, buf_ws);
			}
			if (stInputInfo.inOutMsgChs != NULL ) {
				writeXML_CHS(stInputInfo.inOutMsgChs, buf_ws);
			}
			if (stInputInfo.inOutMsgJpn != NULL ) {
				writeXML_JPN(stInputInfo.inOutMsgJpn, buf_ws);
			}

			exit(1);
		}
	}
}

int main(int argc, char**arv) {
	S4 nRet;

	sqlite3 *db = NULL;
	const char *zTail;
	sqlite3_stmt * stmt = NULL;
	int tuMax = 0;
	int tuIdx;
	BOOL outFlag = FALSE;
	int i;
	
	/*thread define*/
	pthread_t id_time;

	/*arg num check*/
	if (argc <= 1) {
		printf("RUN IT LIKE: rule -conf [param1] -ws [param2]\n");
		return 0;
	}

	if (argc > 5) {
		printf("ERROR: too many arguments!\n");
		return 1;
	} else if (argc < 5) {
		printf("ERROR: arguments not enough!\n");
		return 1;
	}

	/*-conf*/
	strcpy(buf_conf, arv[1]);
	if (strcmp(buf_conf, "-conf")) {
		printf("ERROR: no '-conf' or '-conf' error!\n");
		return 1;
	}
	strcpy(buf_conf, arv[2]);

	/*-ws*/
	strcpy(buf_ws, arv[3]);
	if (strcmp(buf_ws, "-ws")) {
		printf("ERROR: no '-ws' or '-ws' error!\n");
		return 1;
	}
	strcpy(buf_ws, arv[4]);

	if (buf_ws[strlen(buf_ws) - 1] != PATH_DELIMITER) {
		buf_ws[strlen(buf_ws)] = PATH_DELIMITER;
	}

	/*analyzeInput*/
	analyzeInput(buf_conf, buf_ws);

	if (stInputInfo.inDbPath == NULL ) {
		printf("ERROE: no DB-input path!\n");
		freeIO();
		return 1;
	}

	if (stInputInfo.inOutMsgEng == NULL ) {
		printf("WARNING: no XML_ENG-output path!\n");
	} else {
		outFlag = TRUE;
	}

	if (stInputInfo.inOutMsgChs == NULL ) {
		printf("WARNING: no XML_CHS-output path!\n");
	} else {
		outFlag = TRUE;
	}

	if (stInputInfo.inOutMsgJpn == NULL ) {
		printf("WARNING: no XML_JPN-output path!\n");
	} else {
		outFlag = TRUE;
	}

	if (!outFlag) {
		printf("ERROR: no XML-output path!\n");
		freeIO();
		return 1;
	}

	if (!stInputInfo.hasRule) {
		printf("ERROR: no selected rule!\n");
		freeIO();
		return 1;
	}

	/*open core*/
	nRet = CCoreStart();
	if (nRet != COEXIT_SUCCESS) {
		printf("sucks!\n");
		return 1;
	}

	/*open db*/
	if (FileCheckExists(stInputInfo.inDbPath) != COEXIT_FOUND) {
		printf("ERROR: %s not found!\n", stInputInfo.inDbPath);
		return 1;
	}
	sqlite3_open(stInputInfo.inDbPath, &db);
	sqlite3_prepare(db, "SELECT MAX(TblIndex) FROM _TransUnit;", -1, &stmt,
			&zTail);
	if (sqlite3_step(stmt) == SQLITE_ROW) {
		tuMax = sqlite3_column_int(stmt, 0);
	}

	/*open all rules*/
	RuleInitial();
	
	/*start timer*/
	g_time_start = time(NULL);
	nRet = pthread_create(&id_time,NULL,(void *) thread_time,NULL);
	if(nRet){
		printf ("ERROR:Create pthread error!\n");
		return 1;
	}

	for (tuIdx = 1; tuIdx <= tuMax; tuIdx++) {
		/*load unit data*/
		loadUnitCppData(db, tuIdx);
		loadUnitCcData(db, tuIdx);
		/*load used info: transunit, location*/
		loadCgTu(db);
		loadLocation(db);

		/*cpp rule check*/
		for (i = 1; i <= CDirectiveInfo.getMax(); i++) {
			RuleMain_cpp(i, tuIdx);
		}

		/*unit trace and rule check*/
		TraceTranslationUnit(tuIdx,
				OPT_DECLARATION | OPT_DECLARATOR | OPT_STATEMENT
						| OPT_EXPRESSION | OPT_INITEXPRLIST, 0x3f, RuleMain_ast,
				NULL );

		/*close unit trace*/
		TraceClose();
		/*clear unit data*/
		clearUnitCpp();
		clearUnitCc();
	}
	/*load cg data*/
	loadLocation(db);
	loadOption(db);
	loadCgData(db);

	/*cg trace and rule check*/
	Tr_CmdAddCallBackEvent("/event_command_list");
	Tr_CmdAddOption("-skip_callee");
	int funcIdx;
	int funcMax = LinkFunction.getMax();
	for (funcIdx = MIN_ARRAY ; funcIdx <= funcMax; funcIdx++) {
		Tr_CmdAddFunctionEntry(LinkFunction.getName(funcIdx));
	}
	/*close cg trace*/
	Tr_CmdTraceAllEntries(RuleMain_cmd, NULL );
	Tr_CmdCleanEntry();

	/*output NG info*/
	if (!(buf_ws[0] == '/' || buf_ws[1] == ':')) {
		strcpy(buf_conf, buf_ws);
		getcwd(buf_ws, OS_FULLPATH);
		if (buf_ws[strlen(buf_ws) - 1] != PATH_DELIMITER) {
			buf_ws[strlen(buf_ws)] = PATH_DELIMITER;
		}
		strcat(buf_ws, buf_conf);
	}
	if (stInputInfo.inOutMsgEng != NULL ) {
		writeXML_ENG(stInputInfo.inOutMsgEng, buf_ws);
	}
	if (stInputInfo.inOutMsgChs != NULL ) {
		writeXML_CHS(stInputInfo.inOutMsgChs, buf_ws);
	}
	if (stInputInfo.inOutMsgJpn != NULL ) {
		writeXML_JPN(stInputInfo.inOutMsgJpn, buf_ws);
	}
	
	/*close all rules*/
	RuleClose();

	/*close IO*/
	freeIO();

	/*close db*/
	sqlite3_close(db);

	/*close core*/
	CCoreTerminate();

	printf("\n\nend time.(%d s)\n",time(NULL)-g_time_start);

	return 1;
}
